package com.sxt.core.utils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sxt.core.anno.AutoBuilder;
import com.sxt.core.anno.Inject;
import com.sxt.core.model.BeanDefine;

/**
 * 实现包扫描的工具类，根据报名扫描类名
 * @author Liushuangxi
 *
 */
public class PackageScanUtil {

	/**
	 * 传入包名，得到类名的集合
	 * @param packageNames
	 *  包名
	 * @return
	 *  类名集合
	 */
	public static List<String> packageScan(String packageNames){
		// 类名如：com.sxt.service.impl
		String[] packageNameStr = packageNames.split(",");
		//存放类名的集合->[BeanDefine, BeanLabel]
		List<String> classNameList = new ArrayList<String>();
		for (String packageName : packageNameStr) {
			// 得到项目路径名
			String projectPath = PackageScanUtil.class.getClassLoader().getResource("").getPath();
			// 得到包名的路径名
			String f1 = packageName.replaceAll("\\.", "/");
			//得到项目的路径地址
			String realpath = projectPath+f1;
			//扫描文件路径下的文件
			File fileDir = new File(realpath);
			//判断是否是文件夹
			if(fileDir.isDirectory()) {
				// 得到列出路径下所有的文件，并遍历
				String[] classNames= fileDir.list();
				for (String className : classNames) {
					//截取文件的文件名，BeanDefine.class->BeanDefine
					className = className.substring(0, className.lastIndexOf("."));
					// 将文件名存入集合
					classNameList.add(packageName+"."+className);
				}
			}
		}
		return classNameList;
	}
	
	/**
	 * 通过类名或类名的集合，初始化预定义对象
	 * @param classNames
	 * 	类名
	 * @return
	 *  预定义对象
	 */
	public static List<BeanDefine> beanDefineInit(List<String> classNames){
		// 初始化预定义对象的集合
		List<BeanDefine> beanDefines = new ArrayList<BeanDefine>();
		for (String className : classNames) {
			try {
				// 创建className对象
				Class<?> clazz = Class.forName(className);
				//查看该类是否存在注解
				AutoBuilder autoBuilder = clazz.getAnnotation(AutoBuilder.class);
				// 若autoBuilde不为空，表示存在注解，此时创建对象
				if(null!=autoBuilder) {
					String id = autoBuilder.id();
					if(id.equals("")) {
						// 得到类的简写名称
						String name = clazz.getSimpleName();
						// 例如：BeanDefine->beanDefine
						String n=(name.charAt(0)+"").toLowerCase();
						id = n+name.substring(1, name.length());
					}
					// 得到属性名称
					Field[] fields = clazz.getDeclaredFields();
					// 类似于xml文件里面的property文件的name，value/ref(注入的对象，但是对象一般使用类型)
					Map<String, Object> props = new HashMap<String,Object>();
					for (Field field : fields) {
						// 得到注解的属性值
						Inject inject = field.getAnnotation(Inject.class);
						if(null!=inject) {
							// inject.value() == "" type  值注入
							props.put(field.getName(), inject.value());	
						}
					}
					beanDefines.add(new BeanDefine(id, className, props));
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		return beanDefines;
	}
	
	/**
	 * 包扫描并得到对象的定义对象
	 * @param packages
	 * @return
	 */
	public static List<BeanDefine> packagSanAndGetBeanDefine(String packages){
		// 得到包扫描结果集
		List<String> packageScan = packageScan(packages);
		// 得到预定义对象结果集
		List<BeanDefine> beanDefineInit = beanDefineInit(packageScan);
		return beanDefineInit;
	}
	
	public static void main(String[] args) {
		List<BeanDefine> list = packagSanAndGetBeanDefine("com.sxt.core.model");
		System.out.println(list);
	}
}
